package controleFerroviario;

import interfacesFerrovia.TratadorDeEventos;
import interfacesFerrovia.DefsGlobais.TipoAtributo;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import malhaFerroviaria.Ferrovia;
import utils.ComparaItens;
import utils.Utils;
import elementos.Chave;
import elementos.Composicao;
import elementos.Trecho;

public class Controle implements TratadorDeEventos {
	Utils u = new Utils();
	Ferrovia ferrovia = Ferrovia.getInstance();
	HashMap<String, Object> elementos = null;
	HashMap<String, ArrayList<String>> idElementos = null;
	HashMap<Integer, ArrayList<Object[]>> agenda = new HashMap<Integer, ArrayList<Object[]>>();
	HashMap<String, ArrayList<Integer>> elementosAgendados = new HashMap<String, ArrayList<Integer>>();
	List<String> composicoesUltimoTrecho = new ArrayList<String>();

	public void alarmeComposicao(String idComposicao, int instanteAtual,
			TipoFalha tipoDeFalha) {
		
//		ferrovia.frearComposicao(idComposicao, 0, true);
		
		//		System.out.println("alarmeComposicao: " + "idComposicao" + idComposicao + "   intanteAtual" + instanteAtual + "    tipodeFalha" + tipoDeFalha);
	}


	public void partidaComposicao(String idComposicao, int instanteAtual, String idTrecho) {
		
		if(elementos == null)
			inicializaElementos();
		
		// Agenda chamada para mudanca de chave da composicao
		if (!u.verificaUltimoTrecho(idComposicao).equalsIgnoreCase(idTrecho)) {
			addAgendaMudancaChave(idComposicao, idTrecho, instanteAtual);
		}
		
		//System.out.println("tamtrecho: " + ferrovia.consultaAtributo(idTrecho, TipoAtributo.DISTANCIA));
		System.out.println("partidaComposicao: " + "idComposicao" + idComposicao + "    instanteAtual" + instanteAtual + "   idTrecho" + idTrecho + " acel" + ferrovia.consultaAtributo(idComposicao, TipoAtributo.ACEL_ATUAL));
	}

	public void chegadaComposicao(String idComposicao, int instanteAtual,
			String idTrecho){
		//ferrovia.frearComposicao(idComposicao, 0.000000f, Boolean.TRUE);

		System.out.println("chegadaComposicao: idCompo "+ idComposicao + " instante atual "+ instanteAtual + " idTrecho "+ idTrecho);
		System.out.println("posicao chegada: " + ferrovia.consultaAtributo(idComposicao, TipoAtributo.POSICAO_ATUAL));
		System.out.println("velocidade chegada: " + ferrovia.consultaAtributo(idComposicao, TipoAtributo.VEL_ATUAL));
	}

	
	public void alarmeChave(String idChave, int instanteAtual,
			TipoFalha tipoDeFalha){
		System.out.println("alarmeChave idChave "+ idChave+" instantAtual "+ instanteAtual + "tipo de falha "+ tipoDeFalha);
	}

	public void passagemComposicao(String idTrecho, int instanteAtual,
			float posicao, String idComposicao, float velocidade,
			boolean sentidoAB){

		//teste
		String idChave;
		
		//if((Float)ferrovia.consultaAtributo(idTrecho, TipoAtributo.DISTANCIA) - 
			//	(Float)ferrovia.consultaAtributo(idComposicao, TipoAtributo.POSICAO_ATUAL) < 500) {
			idChave = this.verificaProxChave(idComposicao, idTrecho);
			this.verificaPrioridade(idChave);
		//}
		// fim do teste
		
		System.out.println("passagemComposicao:  " + "idTrecho: " + idTrecho + " intanteAtual: " + instanteAtual + " posicao: " + posicao + " idComposicao: " + idComposicao + " velocidade: " + velocidade + " sentidoAB: " + sentidoAB);
	}

	
	public void entradaComposicaoChave(String idChave, int instanteAtual,
			String idComposicao, String idTrechoOrigem){
		
		// Atualiza sentido do trecho
		if((Integer)ferrovia.consultaAtributo(idTrechoOrigem, TipoAtributo.N_COMPOSICOES) == 0) {
			((Trecho)elementos.get(idTrechoOrigem)).setSentido(null);
		}
		
		
		//System.out.println("numeroComp: " + ferrovia.consultaAtributo(idTrechoOrigem, TipoAtributo.N_COMPOSICOES));
		System.out.println("entrada composicao chave - " + idChave + "instante atual " + instanteAtual + " idComp " + idComposicao + " id TreOR " + idTrechoOrigem);
	}

	

	public void saidaComposicaoChave(String idChave, int instanteAtual,
		String idComposicao, String idTrechoDestino){
		
		// Atualiza sentido do trecho
		((Trecho)elementos.get(idTrechoDestino)).setSentido((Boolean) ferrovia.consultaAtributo(idComposicao, TipoAtributo.SENTIDO_ATUAL));
		
		//Se é ultimo trecho
		if (u.verificaUltimoTrecho(idComposicao).equalsIgnoreCase(idTrechoDestino)){
//			int ticFreada = u.verificaTicFrearChegada(idTrechoDestino, idComposicao, instanteAtual);
			
//			Float acel = u.acelFrenagem(idTrechoDestino, idComposicao);
//			u.frearComp(idComposicao, idTrechoDestino, acel);
//			composicoesUltimoTrecho.add(idComposicao);
			
			Float acelFreada = u.acelFrenagem(idTrechoDestino, idComposicao);
			u.frearComp(idComposicao, idTrechoDestino, acelFreada);
			atualizaTrocaChave(idComposicao, idTrechoDestino, instanteAtual);
			
			
//			Method m = null;
//			try {
//				m = Utils.class.getMethod("frearComp", String.class, String.class, FLoat.class);
//			} catch (Exception e) {}
//			
//			
//			Object[] parametros = new Object[3];
//			parametros[0] = idComposicao;
//			parametros[1] = idTrechoDestino;
//			parametros[2] = acelFreada;
//			
//			addAgenda(m, ticFreada, idComposicao, parametros);
			
		//Se não é o ultimo
		}else{
			addAgendaMudancaChave(idComposicao, idTrechoDestino, instanteAtual);
		}
				
		
		System.out.println(" saidaComposicaoChave id chave "+ idChave + "inst atual "+ instanteAtual + "idComp " + idComposicao + "idTreDEst " + idTrechoDestino);
	}


	public void atualizaTrocaChave(String idComposicao, String idTrecho, int instanteAtual){
		ArrayList<Integer> agendados = elementosAgendados.get(idComposicao);
		if (agendados != null){
			for (int i : agendados){
				if (agenda.get(i) != null){
					for (Object[] o : agenda.get(i)){
						Method m = (Method)o[0];
						if (m.getName().equalsIgnoreCase("posicionaChave")){
							agenda.remove(i);
							addAgendaMudancaChave(idComposicao, idTrecho, instanteAtual);
						}
					}
				}
			}
		}
	}
	
	public void tic (int instanteAtual){
//		if (elementos == null)
//			inicializaElementos();
		
		
//		if (!composicoesUltimoTrecho.isEmpty()){
//			for (int i = 0; i < composicoesUltimoTrecho.size(); i++){
//				String idComposicao = composicoesUltimoTrecho.get(i);
//				String idTrecho = (String)ferrovia.consultaAtributo(idComposicao, TipoAtributo.ID_TR_CH_ATUAL);
//				//System.out.println("POSICAO "+ferrovia.consultaAtributo(idComposicao, TipoAtributo.POSICAO_ATUAL));
//
//					Float acel = u.acelFrenagem(idTrecho, idComposicao);
//					u.frearComp(idComposicao, idTrecho, acel);
//			}
//			
//		}
//		
		ArrayList<Object[]> metodos = agenda.get(instanteAtual);
		if (metodos != null){
			for (Object[] o : metodos){
				try {
					if (o[1] == null)
						((Method)o[0]).invoke(u);
					else{
						((Method)o[0]).invoke(u, (Object[])o[1]);
					}
					
					System.out.println("POSICAO ATUAL"+ferrovia.consultaAtributo("comp01", TipoAtributo.POSICAO_ATUAL));
				} catch (Exception e) {} 
			}
		}
		
	}
	
	
	public void inicializaElementos(){
		this.idElementos = getIdElementos();
		this.elementos = getElementos();
		this.inicializaSentidoTrechos();
		//System.out.println("TESTEEEEEEEE");
	}
	

	public HashMap<String, ArrayList<String>> getIdElementos(){
		HashMap<String, ArrayList<String>> idElementos = new HashMap<String, ArrayList<String>>();
		String[] elementos = ferrovia.consultaElementos();
		
		
		for (String s : elementos){

			if ((TipoElemento)ferrovia.consultaAtributo(s, TipoAtributo.TIPO) == TipoElemento.COMPOSICAO){
				ArrayList<String> aux;
				
				if(idElementos.get("comp") != null){
					aux = idElementos.get("comp"); 
				}else{
					aux = new ArrayList<String>();
				}
				
				aux.add(s);
				idElementos.put("comp", aux);
				
			}else if ((TipoElemento)ferrovia.consultaAtributo(s, TipoAtributo.TIPO) == TipoElemento.TRECHO){
				
				ArrayList<String> aux;
				
				if(idElementos.get("t") != null){
					aux = idElementos.get("t"); 
				}else{
					aux = new ArrayList<String>();
				}
				
				aux.add(s);
				idElementos.put("t", aux);
				
			}else if ((TipoElemento)ferrovia.consultaAtributo(s, TipoAtributo.TIPO) == TipoElemento.CHAVE){
				
				ArrayList<String> aux;
				
				if(idElementos.get("ch") != null){
					aux = idElementos.get("ch"); 
				}else{
					aux = new ArrayList<String>();
				}
				aux.add(s);
				idElementos.put("ch", aux);
			} 
			
		}
		
		return idElementos;
	}

	
	public HashMap<String, Object> getElementos(){
		HashMap<String, Object> elementos = new HashMap<String, Object>();
		
		for (String s : this.idElementos.get("comp")){
			elementos.put(s, new Composicao(s, ferrovia));
		}
		
		for (String s : this.idElementos.get("t")){
			elementos.put(s, new Trecho(s, ferrovia));
		}

		for (String s : this.idElementos.get("ch")){
			elementos.put(s, new Chave(s, ferrovia));
		}
		
		return elementos;
	}
	
	// Retorna um set com as composicoes que estao em um determinado trecho
	public Set<Composicao> getComposicoesTrecho(String idTrecho) {
		Set<Composicao> composicoes = new HashSet<Composicao>();

		Iterator<String> it = idElementos.get("comp").iterator();

	    while (it.hasNext()) {
	      String idComposicao = it.next();
	      String idTrechoAtual = (String) ferrovia.consultaAtributo(idComposicao, TipoAtributo.ID_TR_CH_ATUAL);
	      
	      if(idTrechoAtual.equals(idTrecho)) {
	    	  composicoes.add((Composicao) elementos.get(idComposicao));
	      }
	    }
		
		return composicoes;
	}
	

	
	//Agenda metodos para um instante, e atualiza a lista de metodos agendados por elemento
	public Boolean addAgenda(Method m, int instante, String idElemento, Object[] parametros){
		ArrayList<Object[]> objetos = this.agenda.get(instante);
		if (objetos == null)
			objetos = new ArrayList<Object[]>();

			Object[] novo = new Object[2];
			novo[0] = m;
			novo[1] = parametros;

		objetos.add(novo);
		
		ArrayList<Object[]> aux = this.agenda.put(instante, objetos);
		if (aux == null)
			return false;

		if (idElemento != null){
			ArrayList<Integer> agendados = elementosAgendados.get(idElemento);
			if(agendados == null)
				agendados = new ArrayList<Integer>();

			agendados.add(instante);

			this.elementosAgendados.put(idElemento, agendados);
		}
		return true;
	}
	
	
	// Inicializa sentido de todos os trechos
	public void inicializaSentidoTrechos() {
		Iterator<String> it = idElementos.get("comp").iterator();
		
	    while (it.hasNext()) {
		      String idComposicao = it.next();
		      String idTrechoAtual = (String) ferrovia.consultaAtributo(idComposicao, TipoAtributo.ID_TR_CH_ATUAL);
		      
			// Seta o sentido do trecho
		    ((Trecho)elementos.get(idTrechoAtual)).setSentido((Boolean) ferrovia.consultaAtributo(idComposicao, TipoAtributo.SENTIDO_ATUAL));
	    }  
	}
	

	
	// Altera a velocidade de todas as composicoes em um determinado trecho
	public boolean alteraVelocidadeTrecho(String idTrecho, Float novaVelocidade) {
		Set<Composicao> composicoes = getComposicoesTrecho(idTrecho);
		
		if(composicoes != null) {
			Iterator<Composicao> it = composicoes.iterator();
		    while (it.hasNext()) {
		    	Composicao comp = it.next();
			    if(comp.getVelocidade_atual() < novaVelocidade) {
			    comp.setVelocidade_atual(novaVelocidade);
			    ferrovia.acelerarComposicao(comp.getId(), novaVelocidade, true);
			    } else {
				comp.setVelocidade_atual(novaVelocidade);
				ferrovia.frearComposicao(comp.getId(), novaVelocidade, true);
			    }
		    }
		    return true;
		}
		
		return false;
	}

	
	// Agenda mudanca de chave quando uma composicao entra em um trecho
	public int agendaMudancaChave(String idComposicao, String idTrecho, int instanteAtual) {
		int tic = 0;
		int margemSeguranca = 10;
		
		// Verifica proximo trecho
		String idTrechoA = "";
		String idTrechoB = "";
		
		idTrechoA = idTrecho;
		
		String itinerario[] = (String[]) ferrovia.consultaAtributo(idComposicao, TipoAtributo.ITINERARIO);

		boolean aux = false;
		for(String s : itinerario) {
			if (aux){
				idTrechoB = s;
				break;
			}
			if (s.equalsIgnoreCase(idTrechoA))
				aux = true;	
		}
		
		System.out.println("chaveA: " + idTrechoA + "- chaveB: " + idTrechoB);
		
		// Verifica a chave que a composicao ira entrar
		String idProxChave = "";
		Iterator<String> it = idElementos.get("ch").iterator();

	    while (it.hasNext()) {
	      String idChave = it.next();
    	  String trechosA[] = (String[])ferrovia.consultaAtributo(idChave, TipoAtributo.TRECHOS_A);
	      
	      if ((Boolean) ferrovia.consultaAtributo(idComposicao, TipoAtributo.SENTIDO_ATUAL) == true) {
	    	  
	    	  for (String s : trechosA) {
	    		  if (s.equals(idTrechoA)) {
	    			  idProxChave = idChave;
	    		  }
	    	  }    	  
	    	  
	      } else {
	    	  
	    	  String trechosB[] = (String[])ferrovia.consultaAtributo(idChave, TipoAtributo.TRECHOS_B);
	    	  for (String s : trechosB) {
	    		  if (s.equals(idTrechoA)) {
	    			  idProxChave = idChave;
	    		  }
	    	  }
	      }
	    }
	    
	    System.out.println("proxChave: " + idProxChave);
	    
	    // Verifica tempo de mudanca da chave
		int tempoMudanca = 0;

		tempoMudanca = (Integer) ferrovia.consultaAtributo(idProxChave, TipoAtributo.TEMPO_MUDANCA);
		
		// Verifica tempo que a comp ira demorar para chegar a chave
		int tempoChegada = 0;
		Float tamanhoTrecho = (Float) ferrovia.consultaAtributo(idTrechoA, TipoAtributo.DISTANCIA);
		Float posAtual = ferrovia.consultaPosicao(idComposicao, instanteAtual);
		
		if ((Boolean)ferrovia.consultaAtributo(idComposicao, TipoAtributo.SENTIDO_ATUAL)) {
			tempoChegada = ferrovia.consultaTempo(idComposicao, Math.abs(tamanhoTrecho-posAtual));
		} else {
			tempoChegada = ferrovia.consultaTempo(idComposicao, Math.abs(posAtual-tamanhoTrecho));
			Float velAtual = (Float) ferrovia.consultaAtributo(idComposicao, TipoAtributo.VEL_ATUAL);
//			tempoChegada = u.calculaTempoChegadaAB(velAtual, Math.abs(posAtual));
		}
		
		System.out.println("MUDANCA CHAVE- COMPOSICAO " + idComposicao);
		System.out.println("SENTIDO " + (Boolean)ferrovia.consultaAtributo(idComposicao, TipoAtributo.SENTIDO_ATUAL));
		System.out.println("PosicaoAtual: " + posAtual);
		System.out.println("TempoMudanca: " + tempoMudanca);
		System.out.println("TempoChegada: " + tempoChegada);
		System.out.println("instanteAtual: " + instanteAtual);
		
		
		tic = Math.abs(tempoChegada - tempoMudanca - margemSeguranca + instanteAtual);
				
		return tic;
	}
	
	// Adiciona na agenda o evento de mudanca de chave
	public void addAgendaMudancaChave(String idComposicao, String idTrecho, int instanteAtual) {
		int tic = agendaMudancaChave(idComposicao, idTrecho, instanteAtual);
		
		System.out.println("tic agendado: " + tic + "  instante: " + instanteAtual);
		
		Method m = null;
		try {
			m = Utils.class.getMethod("posicionaChave", String.class, String.class);
		} catch (Exception e) {}
		
		Object[] parametros = new Object[2];
		parametros[0] = idComposicao;
		parametros[1] = verificaProxChave(idComposicao, idTrecho);
		
		addAgenda(m, tic, idComposicao, parametros);
	}
	
	
	// Verifica proxima chave a partir de um trecho
	public String verificaProxChave(String idComposicao, String idTrecho) {
		String idProxChave = "";
		Iterator<String> it = idElementos.get("ch").iterator();

	    while (it.hasNext()) {
	      String idChave = it.next();
	      
	      if ((Boolean) ferrovia.consultaAtributo(idComposicao, TipoAtributo.SENTIDO_ATUAL) == true) {
	    	  
	    	  String trechosA[] = (String[])ferrovia.consultaAtributo(idChave, TipoAtributo.TRECHOS_A);
	    	  for (String s : trechosA) {
	    		  if (s.equals(idTrecho)) {
	    			  idProxChave = idChave;
	    		  }
	    	  }    	  
	    	  
	      } else {
	    	  
	    	  String trechosB[] = (String[])ferrovia.consultaAtributo(idChave, TipoAtributo.TRECHOS_B);
	    	  for (String s : trechosB) {
	    		  if (s.equals(idTrecho)) {
	    			  idProxChave = idChave;
	    		  }
	    	  }
	      }
	    }
	    
	    return idProxChave;
	}

	
	// Verifica se o sentido da composicao eh igual ao sentido do trecho destino
	public Boolean verificaSentidoTrechoDestino(String idComposicao, String idTrecho) {
		
		if ((Boolean) ferrovia.consultaAtributo(idComposicao, TipoAtributo.SENTIDO_ATUAL) == 
			((Trecho)elementos.get(idTrecho)).getSentido()) {
			return true;
		}
		
		return false;
	}
	
	//verifica qual a composicao que esta mais proxima da chave
	// retorna null se nenhum trem esta no trecho
	public Composicao fimDaLinha(String extremidade, String idChave, String idTrecho) {
		Composicao comp = null;
		Float posicao = 0f;
		Set<Composicao> compTrecho;
		Float posicao2 = Float.MAX_VALUE;
		
		compTrecho = this.getComposicoesTrecho(idTrecho);
		
		if(extremidade == "A") {
		
			for(Composicao c : compTrecho) {
				if((Float) ferrovia.consultaAtributo(c.getId(), TipoAtributo.POSICAO_ATUAL) >= posicao) {
					comp = c;
					posicao = (Float) ferrovia.consultaAtributo(c.getId(), TipoAtributo.POSICAO_ATUAL);
				}
			}
		} else {

			for(Composicao c2 : compTrecho) {
				if((Float) ferrovia.consultaAtributo(c2.getId(), TipoAtributo.POSICAO_ATUAL) <= posicao2) {
					comp = c2;
					posicao2 = (Float) ferrovia.consultaAtributo(c2.getId(), TipoAtributo.POSICAO_ATUAL);
				}
			}
		}
		return comp;
	}
	
	//Efetua o controle de entrada de composicoes na chave (terminar)
	public void verificaPrioridade(String idChave) {
		List<String> listComp = new ArrayList<String>(); // lista das ids das composicoes proximas da chave
		Composicao comp, CompAnterior;
		String id_tr_ch_atual;
		String[] trechos_a = (String[]) ferrovia.consultaAtributo(idChave, TipoAtributo.TRECHOS_A);
		String[] trechos_b = (String[]) ferrovia.consultaAtributo(idChave, TipoAtributo.TRECHOS_B);
		int i, tempoPercorrerChave, tempoMudancaChave, tempoTotal;
		Float velAtualCompAnt, distChave, novaAceleracao, velAtualComp, distCompChave, novaVelocidade;
		
		//gera lista com as composicoes que atravessarao uma chave
		for(i = 0; i < trechos_a.length; i++) {
			comp = this.fimDaLinha("A", idChave, trechos_a[i]);
			if(comp != null) listComp.add(comp.getId());
		}
		
		for(i = 0; i < trechos_b.length; i++) {
			comp = this.fimDaLinha("B", idChave, trechos_b[i]);
			if(comp != null) listComp.add(comp.getId());
		}
		
		// ordena lista de composicoes pelo tempo de chegada a chave 
		Collections.sort(listComp, new ComparaItens());
		
		// ajuste da velocidade e aceleracao para que nao ocorra colisao na chave
		i = 0;
		CompAnterior = (Composicao) elementos.get(listComp.get(i)); // consertar isso
		listComp.remove(0); //primeira composicao tem a maior prioridade
		distChave = (Float) ferrovia.consultaAtributo(idChave, TipoAtributo.DISTANCIA);
		
		for(String idComp : listComp) {
			if((Boolean) ferrovia.consultaAtributo(idComp, TipoAtributo.EM_MOVIMENTO)) {
				String idCompAnterior = CompAnterior.getId();
				velAtualCompAnt = (Float) ferrovia.consultaAtributo(idCompAnterior, TipoAtributo.VEL_ATUAL);

				tempoPercorrerChave = u.calculaTempoChegadaAB(velAtualCompAnt, distChave);
				tempoMudancaChave = (Integer) ferrovia.consultaAtributo(idChave, TipoAtributo.TEMPO_MUDANCA);

				// adicionado margem de seguranca
				tempoTotal = tempoPercorrerChave + tempoMudancaChave + 500;

				velAtualComp = (Float) ferrovia.consultaAtributo(idComp , TipoAtributo.VEL_ATUAL);

				id_tr_ch_atual = (String) ferrovia.consultaAtributo(idComp, TipoAtributo.ID_TR_CH_ATUAL);
				distCompChave = (Float) ferrovia.consultaAtributo(id_tr_ch_atual, TipoAtributo.DISTANCIA) - (Float) ferrovia.consultaAtributo(idComp, TipoAtributo.POSICAO_ATUAL);

				// ajusta nova velocidade da composicao 
				novaAceleracao = u.calculaFrenagemComposicao(idComp, velAtualComp, tempoTotal, distCompChave);
				novaVelocidade = u.calculaVelFinal(velAtualComp, novaAceleracao, tempoTotal);

				ferrovia.acelerarComposicao(idComp, novaVelocidade, novaAceleracao);

				CompAnterior = (Composicao) elementos.get(idComp);
			}
		}
		System.out.println("AJUSTOU PRIORIDADES");
	}
	
	public List<String> verificaConflitoTrechos(String[] trechosA, String[] trechosB){
		List<String> listaPrioridade = new LinkedList<String>();
		Boolean conflito = false;
		
		for (String a : trechosA){
			for (String b : trechosB){
				String proxTreA = u.verificaProximoTrecho(a);
				String proxTreB = u.verificaProximoTrecho(b);
				String treAtualA = (String) ferrovia.consultaAtributo(a, TipoAtributo.ID_TR_CH_ATUAL);
				String treAtualB = (String) ferrovia.consultaAtributo(b, TipoAtributo.ID_TR_CH_ATUAL);
				Boolean sentA = ((Trecho)elementos.get(a)).getSentido();
				Boolean sentB = ((Trecho)elementos.get(b)).getSentido();

				
				if (proxTreA.equalsIgnoreCase(treAtualB) && sentA != sentB){
					conflito = true;
					if(proxTreB.equalsIgnoreCase(treAtualA)){
						//GERAR EXCEPTION

						alteraVelocidadeTrecho(a, 0f);
						alteraVelocidadeTrecho(b, 0f);
					}else{

						int indiceA = listaPrioridade.indexOf(a);
						int indiceB = listaPrioridade.indexOf(b);

						if (indiceA == -1){
							listaPrioridade.add(a);
						}

						if (indiceB == -1){
							listaPrioridade.add(listaPrioridade.indexOf(a), b);
						}

						indiceA = listaPrioridade.indexOf(a);
						indiceB = listaPrioridade.indexOf(b);

						if(indiceA < indiceB){
							listaPrioridade.remove(b);
							listaPrioridade.add(listaPrioridade.indexOf(a), b);
						}
					}
				}
			}
		}

		for (String b : trechosB){
			for (String a : trechosA){
				String proxTreA = u.verificaProximoTrecho(a);
				String proxTreB = u.verificaProximoTrecho(b);
				String treAtualA = (String) ferrovia.consultaAtributo(a, TipoAtributo.ID_TR_CH_ATUAL);
				String treAtualB = (String) ferrovia.consultaAtributo(b, TipoAtributo.ID_TR_CH_ATUAL);
				Boolean sentA = ((Trecho)elementos.get(a)).getSentido();
				Boolean sentB = ((Trecho)elementos.get(b)).getSentido();
				
				if (proxTreB.equalsIgnoreCase(treAtualA) && sentA != sentB){
					conflito = true;
					if(proxTreA.equalsIgnoreCase(treAtualB)){
						//GERAR EXCEPTION

						alteraVelocidadeTrecho(a, 0f);
						alteraVelocidadeTrecho(b, 0f);
					}else{
						int indiceA = listaPrioridade.indexOf(a);
						int indiceB = listaPrioridade.indexOf(b);

						if (indiceB == -1){
							listaPrioridade.add(b);
						}

						if (indiceA == -1){
							listaPrioridade.add(listaPrioridade.indexOf(b), a);
						}

						indiceA = listaPrioridade.indexOf(a);
						indiceB = listaPrioridade.indexOf(b);

						if(indiceB < indiceA){
							listaPrioridade.remove(a);
							listaPrioridade.add(listaPrioridade.indexOf(b), a);
						}
					}
				}
			}
		}
		if (conflito)
			return listaPrioridade;
		else
			return null;
	}
	
}
